using System;
using System.Drawing.Design;
using System.Windows.Forms;
using OpenComposite.Base.Collections;
using OpenComposite.Main.Properties;
using OpenComposite.EII;
using OpenComposite.EII.Designer;
using OpenComposite.EII.Designer.SCA;
using OpenComposite.EII.Designer.Workflow;
using OpenComposite.EII.Repository;
using OpenComposite.EII.Services;
using WeifenLuo.WinFormsUI.Docking;

namespace OpenComposite.SOBADesigner
{
	/// <summary>
	/// This is the main controller for the soba designer. 
	/// It manages the events from the project tree, detail view and all other designers.
	/// </summary>
	internal class ComponentDesignerController : OpenComposite.EII.IMainController
	{
		#region Initialization
		public ComponentDesignerController(DockPanel dockPanel, RepositorySurfaceManager surfaceManager)
		{
			_dockPanel = dockPanel;
			_surfaceManager = surfaceManager;

			init();
		}
		private void init()
		{
			_controllerWF = new WorkflowController(_dockPanel, _surfaceManager);

			_frmDomainEditor = new formDomainEditor(_surfaceManager);
			_dockDomainTrees = new DockContent();
			_ucTrees = new UCComponentTrees(_surfaceManager);
			_toolboxService = new MainToolboxService(_surfaceManager);
			//
			// _frmDomainEditor
			//
			_frmDomainEditor.UpdateItem += new EventHandler<ItemSelectedEventArgs>(_frmDomainEditor_UpdateItem);
			_frmDomainEditor.FormClosed += new System.Windows.Forms.FormClosedEventHandler(_frmDomainEditor_FormClosed);
			//
			// _ucTrees
			//
			_ucTrees.Dock = System.Windows.Forms.DockStyle.Fill;
			_ucTrees.DeleteItem += new EventHandler<ItemSelectedEventArgs>(_ucTrees_DeleteItem);
			_ucTrees.ItemSelected += new EventHandler<ItemSelectedEventArgs>(_ucTrees_ItemSelected);
			_ucTrees.CreateProcessForMethod += new EventHandler<ItemSelectedEventArgs>(_ucTrees_CreateProcessForMethod);
			_ucTrees.AddDiagram += new EventHandler<ItemSelectedEventArgs>(_ucTrees_AddDiagram);
			_ucTrees.OpenDiagram += new EventHandler<ItemSelectedEventArgs>(_ucTrees_OpenDiagram);
			//
			// _dockDomainTrees
			//
			_dockDomainTrees.TabText = "Project Explorer";
			_dockDomainTrees.CloseButton = false;
			_dockDomainTrees.ShowHint = DockState.DockLeft;
			_dockDomainTrees.Icon = OpenComposite.Repository.Properties.Resources.ico_solutionexplorer;
			_dockDomainTrees.Controls.Add(_ucTrees);
			//
			// _dockPanel
			//
			_dockPanel.ActiveDocumentChanged += new EventHandler(_dockPanel_ActiveDocumentChanged);
			//
			// _surfaceManager
			//
			_surfaceManager.AddService(typeof(IRepositoryExplorerView), _ucTrees);
			_surfaceManager.AddService(typeof(IMainController), this);
			_surfaceManager.AddService(typeof(DockPanel), _dockPanel);
			_surfaceManager.AddService(typeof(IToolboxService), _toolboxService);
		}

		private void initFrmDomainEditorOnly()
		{
			_frmDomainEditor = new formDomainEditor(_surfaceManager);
			//
			// _frmDomainEditor
			//
			_frmDomainEditor.UpdateItem += new EventHandler<ItemSelectedEventArgs>(_frmDomainEditor_UpdateItem);
			_frmDomainEditor.FormClosed += new System.Windows.Forms.FormClosedEventHandler(_frmDomainEditor_FormClosed);
		}

		#endregion

		#region Public Members

		#region Properties
		/// <summary>
		/// Gets the repository service.
		/// </summary>
		public RepositoryService Repository
		{
			get { return (RepositoryService)GetService(typeof(RepositoryService)); }
		}
		#endregion

		#region Events
		public event EventHandler<ItemSelectedEventArgs> CreateProcessForMethod = null;
		public event EventHandler<CreateProcessEventArgs> CreateProcessForComponentOperation = null;
		#endregion

		#region Methods
		public void Show()
		{
			if ( _frmDomainEditor.IsDisposed )
				initFrmDomainEditorOnly();
			Application.DoEvents();
			_toolboxService.DockPanel = _dockPanel;//DockState.DockRightAutoHide); //_dockDomainTrees.Pane, DockAlignment.Bottom, .5f);
			_toolboxService.Refresh();
			_dockDomainTrees.Show(_dockPanel);
			_dockDomainTrees.Refresh();
			_frmDomainEditor.Show(_dockPanel);
			_frmDomainEditor.Refresh();
		}

		public void ShowWorkflowDesigner()
		{
			_controllerWF.Show(_dockPanel);
		}

		public void ShowComponentBinding()
		{
			FormSelectWebServices frmSelectWS = new FormSelectWebServices(_controllerWF);
			frmSelectWS.Show(_dockPanel);
		}

		public void RegisterControllerEvents(IController controller)
		{
			if ( controller != null ) {
				controller.Saved += new EventHandler(dc_DesignerSaved);
				controller.Closed += new EventHandler(dc_DesignerClosed);

				DesignController dc = controller as DesignController;
				if ( dc != null ) {
					dc.CreateProcessForComponentOperation += new EventHandler<CreateProcessEventArgs>(dc_CreateProcessForComponentOperation);
					dc.OpenDiagramOfRepositoryItem += new EventHandler<OpenDiagramEventArgs>(dc_OpenDiagramOfRepositoryItem);
				}
			}
		}
		public void UnRegisterControllerEvents(IController controller)
		{
			if ( controller != null ) {
				controller.Saved -= new EventHandler(dc_DesignerSaved);
				controller.Closed -= new EventHandler(dc_DesignerClosed);

				DesignController dc = controller as DesignController;
				if ( dc != null ) {
					dc.CreateProcessForComponentOperation -= new EventHandler<CreateProcessEventArgs>(dc_CreateProcessForComponentOperation);
					dc.OpenDiagramOfRepositoryItem -= new EventHandler<OpenDiagramEventArgs>(dc_OpenDiagramOfRepositoryItem);
				}
			}
		}

		public void OpenDiagram(IRepositoryItem item)
		{
			RepositoryItemBaseEx itemex = item as RepositoryItemBaseEx;
			if ( itemex != null ) openDiagram(itemex);
		}
		public void ShowDetails(IRepositoryItem item)
		{
			if ( _frmDomainEditor == null ) return;
			_frmDomainEditor.ShowItem(item.RepositoryItemType, item.ID);
		}
		#endregion

		#endregion

		#region Protected Members

		#region Methods
		protected object GetService(Type serviceType)
		{
			if ( _surfaceManager != null )
				return _surfaceManager.GetService(serviceType);
			else
				return null;
		}
		#endregion

		#endregion

		#region Private Members

		#region Fields
		private DockPanel _dockPanel;
		private formDomainEditor _frmDomainEditor;
		private DockContent _dockDomainTrees;
		private UCComponentTrees _ucTrees;
		private WorkflowController _controllerWF;
		private RepositorySurfaceManager _surfaceManager;
		private MainToolboxService _toolboxService;
		#endregion

		#region Methods

		private DockPane findPane(string name, DockPanel dockPanel)
		{
			foreach ( DockPane pane in dockPanel.Panes ) {
				if ( pane.CaptionText == name )
					return pane;
			}
			return null;
		}

		private void doCreateOrchstrationForOperation(CreateProcessEventArgs e)
		{
			bool bSC;
			Operation op = e.Operation;
			BindingListEx<OpenComposite.EII.Repository.Workflow> wfs = Global.Data.GetOperationWorkflow(op.ID);
			OpenComposite.EII.Repository.Workflow wf = null;
			if ( wfs.Count > 0 ) {
				wf = wfs[0];
			} else {
				wf = this.Repository.GetItem(ItemType.Workflow, true, Global.Status.CurrentRepositoryId,
					false, false, out bSC) as OpenComposite.EII.Repository.Workflow;
				if ( wf != null ) {
					wf.Name = RepositoryService.GetIdentifier(e.ComponentSymbol.Text);
					wf.Save();
					op.WorkflowId = wf.ID;
					op.Save();
					Global.Data.AddRepositoryItemToDomainFolder(Global.Status.CurrentDomainId, wf);
					_ucTrees.UpdateCurrentRepository();
				}
			}
			if ( wf != null ) {
				openDiagram(wf);
			}
		}
		private void openDiagram(RepositoryItemBaseEx item)
		{
			_frmDomainEditor.Refresh();
			_frmDomainEditor.SuspendLayout();
			_frmDomainEditor.UseWaitCursor = true;

			IController controller = this.Repository.CreateDesignController(_dockPanel, item, Global.Status.CurrentRepositoryId);
			if ( controller == null )
				System.Windows.Forms.MessageBox.Show("No diagram designer available.", "Open Diagram", System.Windows.Forms.MessageBoxButtons.OK, System.Windows.Forms.MessageBoxIcon.Information);
			else {
				RegisterControllerEvents(controller);
				controller.Show(_dockPanel);
			}
			_frmDomainEditor.UseWaitCursor = false;
			_frmDomainEditor.ResumeLayout(true);
		}

		#endregion

		#region Event Handlers

		private void _frmDomainEditor_UpdateItem(object sender, ItemSelectedEventArgs e)
		{
			if ( e.Node == null &&
				( e.Type == ItemType.Repository || e.Type == ItemType.Organization ) ) {
				_ucTrees.UpdateRepository(e.RepositoryId);
			} else {
				_ucTrees.UpdateTreeNode(e.Node);
				if ( e.Type == ItemType.Diagram )
					_ucTrees_OpenDiagram(sender, e);
			}
		}
		private void _frmDomainEditor_FormClosed(object sender, System.Windows.Forms.FormClosedEventArgs e)
		{
			_dockDomainTrees.Hide();
		}

		private void _ucTrees_AddDiagram(object sender, ItemSelectedEventArgs e)
		{
			IController dc = this.Repository.CreateDesignController(_dockPanel, ItemType.BObject);
			if ( dc == null )
				System.Windows.Forms.MessageBox.Show("No diagram designer available.", "Open Diagram", System.Windows.Forms.MessageBoxButtons.OK, System.Windows.Forms.MessageBoxIcon.Information);
			else
				dc.Show(_dockPanel);

		}
		private void _ucTrees_ItemSelected(object sender, ItemSelectedEventArgs e)
		{
			if ( e.Node == null && e.Type == ItemType.Repository ) {
				_frmDomainEditor.ShowItem(e.Type, e.RepositoryId);
			} else {
				_frmDomainEditor.ShowItem(e.Node);
			}
			_frmDomainEditor.Activate();
		}
		private void _ucTrees_DeleteItem(object sender, ItemSelectedEventArgs e)
		{
			_frmDomainEditor.DeleteItem(e.Node);
		}
		private void _ucTrees_CreateProcessForMethod(object sender, ItemSelectedEventArgs e)
		{
			EventHandler<ItemSelectedEventArgs> tmp = this.CreateProcessForMethod;
			if ( tmp != null )
				tmp(sender, e);
		}
		private void _ucTrees_OpenDiagram(object sender, ItemSelectedEventArgs e)
		{
			if ( e.Node == null ) return; // EXIT

			RepositoryItemBaseEx itemex = e.Node.Tag as RepositoryItemBaseEx;

			if ( itemex == null ) return; // EXIT

			if ( !itemex.LockByCurrentUser() ) {
				User lockedByUser = itemex.GetLockedByUser();
				string msg = "Item is currently locked by another user";
				if ( lockedByUser != null ) {
					msg += " (" + lockedByUser.FormattedName + ")";
				}
				msg += ".";
				MessageBox.Show(msg, itemex.Name + " locked", MessageBoxButtons.OK, MessageBoxIcon.Stop);
				return;
			}

			_frmDomainEditor.Refresh();
			_frmDomainEditor.UseWaitCursor = true;
			_frmDomainEditor.Refresh();
			IController controller = null;
			GenericFolder folder = ( e.Node.Parent != null ? e.Node.Parent.Tag as GenericFolder : null );

			if ( folder != null && folder.AllowedChildTypes.Contains(ItemType.Diagram) ) {
				controller = this.Repository.CreateDesignController(
					_dockPanel, ItemType.SOBA, itemex, e.RepositoryId);
			} else {
				controller = this.Repository.CreateDesignController(
					_dockPanel, itemex, e.RepositoryId);
			}
			if ( controller != null ) {
				RegisterControllerEvents(controller);
				controller.Show(_dockPanel);
			}
			_frmDomainEditor.UseWaitCursor = false;
			_frmDomainEditor.DockPanel.Refresh();
			_frmDomainEditor.Refresh();
		}

		private void dc_CreateProcessForComponentOperation(object sender, CreateProcessEventArgs e)
		{
			doCreateOrchstrationForOperation(e);

			EventHandler<CreateProcessEventArgs> tmp = this.CreateProcessForComponentOperation;
			if ( tmp != null )
				tmp(sender, e);
		}
		private void dc_OpenDiagramOfRepositoryItem(object sender, OpenDiagramEventArgs e)
		{
			if ( e.Item is RepositoryItemBaseEx )
				openDiagram((RepositoryItemBaseEx)e.Item);
		}

		private void dc_DesignerClosed(object sender, EventArgs e)
		{
			IController controller = sender as IController;
			RepositoryItemBaseEx itemex = controller.RepositoryItem as RepositoryItemBaseEx;
			if ( itemex != null ) {
				itemex.UnlockFromCurrentUser();
			}
			UnRegisterControllerEvents(controller);
		}
		private void dc_DesignerSaved(object sender, EventArgs e)
		{
			_ucTrees.UpdateCurrentRepository();
		}

		private void _dockPanel_ActiveDocumentChanged(object sender, EventArgs e)
		{
			//_dockPanel.SuspendLayout(true);
			try {
				if ( _dockPanel.ActiveDocument == _frmDomainEditor ) {
					_surfaceManager.ActiveDesignSurface = null;
				} else {
					DesignerViewDockContent dview = _dockPanel.ActiveDocument as DesignerViewDockContent;
					if ( dview != null ) {
						_surfaceManager.ActiveDesignSurface = dview.Controller.Surface;
					}
				}
			} finally {
				//_dockPanel.ResumeLayout(true, true);
			}
		}

		#endregion

		#endregion
	}
}
